import string

from php4dvd.model.user import User
from php4dvd.model.user import Movie
from php4dvd.pages.internal_page import InternalPage
from php4dvd.pages.login_page import LoginPage
from php4dvd.pages.user_management_page import UserManagementPage
from php4dvd.pages.user_profile_page import UserProfilePage
from php4dvd.pages.add_movie_page import AddMoviePage
from php4dvd.pages.movie_page import MoviePage
from php4dvd.pages.movies_results_page import MoviesResultsPage
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support.expected_conditions import *


class Application(object):
    def __init__(self, driver, base_url):
        driver.get(base_url)
        self.wait = WebDriverWait(driver, 10)
        self.login_page = LoginPage(driver, base_url)
        self.internal_page = InternalPage(driver, base_url)
        self.user_profile_page = UserProfilePage(driver, base_url)
        self.user_management_page = UserManagementPage(driver, base_url)
        self.add_movie_page = AddMoviePage(driver, base_url)
        self.movie_page = MoviePage(driver, base_url)
        self.movies_results_page = MoviesResultsPage(driver, base_url)
        self.movies_list_before = []
        self.movies_list_after = []
        self.movies_list_after_invalid = []
        self.movies_titles = []

    def logout(self):
        self.internal_page.logout_button.click()
        self.wait.until(alert_is_present()).accept()

    def ensure_logout(self):
        element = self.wait.until(presence_of_element_located((By.CSS_SELECTOR, "nav, #loginform")))
        if element.tag_name == "nav":
            self.logout()

    def login(self, user):
        lp = self.login_page
        lp.is_this_page
        lp.username_field.send_keys(user.username)
        lp.password_field.send_keys(user.password)
        lp.submit_button.click()

    def ensure_login_as(self, user):
        element = self.wait.until(presence_of_element_located((By.CSS_SELECTOR, "nav, #loginform")))
        if element.tag_name == "nav":
            # we are on internal page
            if self.is_logged_in_as(user):
                return
            else:
                self.logout()
        self.login(user)

    def is_logged_in(self):
        return self.internal_page.is_this_page

    def is_logged_in_as(self, user):
        return self.is_logged_in() \
            and self.get_logged_user().username == user.username

    def is_not_logged_in(self):
        return self.login_page.is_this_page

    def get_logged_user(self):
        self.internal_page.user_profile_link.click()
        upp = self.user_profile_page
        upp.is_this_page
        return User(username=upp.user_form.username_field.get_attribute("value"),
                    email=upp.user_form.email_field.get_attribute("value"))

    def add_user(self, user):
        self.internal_page.user_management_link.click()
        ump = self.user_management_page
        ump.is_this_page
        ump.user_form.username_field.send_keys(user.username)
        ump.user_form.email_field.send_keys(user.email)
        ump.user_form.password_field.send_keys(user.password)
        ump.user_form.password1_field.send_keys(user.password)
        ump.user_form.submit_button.click()

    def add_movie(self, movie):
        self.movies_results_page.add_movie_link.click()
        amp = self.add_movie_page
        amp.title_field.send_keys(movie.title)
        amp.year_field.send_keys(movie.year)
        amp.save_button.click()

    def is_movie_added(self, movie):
        mp = self.movie_page
        added_title = movie.title+" ("+str(movie.year)+")"
        self.wait.until(presence_of_element_located((By.CSS_SELECTOR, "h2")))
        displayed_title = mp.movie_title.text
        if added_title == displayed_title:
            return True
        else:
            return False

    def remove_movie(self):
        mrp = self.movies_results_page
        self.movies_list_before[0].click()
        mp = self.movie_page
        mp.remove_button.click()
        self.wait.until(alert_is_present()).accept()
        self.wait.until(visibility_of_element_located((By.ID, "results")))
        self.movies_list_after = mrp.movies_list

    def is_movies_list_not_null(self):
        mrp = self.movies_results_page
        self.wait.until(visibility_of_element_located((By.ID, "results")))
        self.movies_list_before = mrp.movies_list
        if len(self.movies_list_before) > 0:
            return True
        else:
            return False

    def is_movie_removed(self):
        if len(self.movies_list_after) == len(self.movies_list_before) - 1:
            return True
        else:
            return False

    def valid_search(self):
        mrp = self.movies_results_page
        self.movies_list_after_invalid = mrp.movies_list
        import random
        search_criteria = random.choice(self.movies_titles)
        mrp.search_field.clear()
        mrp.search_field.send_keys(search_criteria)
        mrp.search_field.send_keys(Keys.RETURN)


    def is_search_success(self):
        mrp = self.movies_results_page
        self.movies_list_after = mrp.movies_list
        while len(self.movies_list_after_invalid) == len(self.movies_list_after):
            self.movies_list_after = mrp.movies_list
        assert len(self.movies_list_after) != 0
        if len(self.movies_list_before) != len(self.movies_list_after):
            return True
        else:
            return False

    def invalid_search(self):
        mrp = self.movies_results_page
        for res in self.movies_list_before:
            self.movies_titles.append(res.text)
        import random
        search_criteria = ''.join([random.choice(string.ascii_letters + string.digits) for i in range(10)])
        while search_criteria in self.movies_titles:
            search_criteria = ''.join([random.choice(string.ascii_letters + string.digits) for i in range(10)])
        mrp.search_field.clear()
        mrp.search_field.send_keys(search_criteria)
        mrp.search_field.send_keys(Keys.RETURN)

    def is_no_results(self):
        self.wait.until(text_to_be_present_in_element((By.XPATH, "//*[@id='results']/div[1]"), "No movies where found."))
        return True